﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core;
using Cofe.Core.Filter;
using Cofe.Core.Implements;
using Cofe.Data.Filter;
using Cofe.Data.Utils.ThirdParty;

namespace Cofe.Data.Filter
{
    [Export(typeof(ICofeService))]
    [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFEDB)]
    public class EntryFilterExpressionFactory : IEntryFilterExpressionFactory
    {
        #region Constructor
        
        #endregion

        #region Methods

        public Expression<Func<CofeSystemInfo, bool>> construct<T>(T entryFilter, params IOptionFilter[] optionFilters)
            where T : IEntryFilter
        {
            var fs = CofeServices.ServiceLocater.TryFindService<IEntryFilterExpression<T>>();
            if (fs == null)
                return (e) => true;
            else return fs.GetQueryExpression(entryFilter, optionFilters);
        }

        public Expression<Func<CofeSystemInfo, bool>> ConstructExpression(FilterCollections filters)
        {
            return ConstructExpression(filters.EntryFilters, filters.OptionFilters);
        }

        private Expression<Func<CofeSystemInfo, bool>> ConstructExpression(IEntryFilter entryFilter, IOptionFilter[] optionFilters)
        {
            var methodInfo = typeof(EntryFilterExpressionFactory).GetMethod("construct").MakeGenericMethod(entryFilter.GetType());
            return (Expression<Func<CofeSystemInfo, bool>>)methodInfo.Invoke(this, new object[] { entryFilter, optionFilters });
        }

        private Expression<Func<CofeSystemInfo, bool>> ConstructExpression(IEntryFilter[] entryFilters, IOptionFilter[] optionFilters)
        {
            if (entryFilters.Length == 0)
                return e => true;

            Expression<Func<CofeSystemInfo, bool>> retVal = null;

            foreach (var ef in entryFilters)
            {
                if (retVal == null)
                    retVal = ConstructExpression(ef, optionFilters);
                else retVal = retVal.And(ConstructExpression(ef, optionFilters));                    
            }

            return retVal;
        }

        #endregion

        #region Data
        
        #endregion

        #region Public Properties
        
        #endregion


       
    }
}
